<?

class ChurroDB{
	protected $connection;				// MySQL link identifier
	protected $error = FALSE;			// Error Message
	protected $now = 0;					// current time stamp
	protected $query = ''; 				// the last sql code executed
	protected $queryCount = 0;			// total number of queries performed on page request
	
	protected $host = DBHOST;				// These are set in config.php
	protected $username = DBUSER;
	protected $password = DBPASS;
	protected $dbname = DBNAME;
	
	private $cache = FALSE;				// whether to use disk (file) caching. not ready for prime time.
	private $cacheCount = 0;			// total number of queries loaded from disk cache
	private $cache_filename = '';	
	private $cache_filepath = '';	
	
	private $affected = 0;				// number of rows affected in update / insert
	private $lastid;					// id of last inserted row
	
	
	public function __construct(){
		$this->now = time();
		
		$this->connectDB( $this->host, $this->username, $this->password );
		if( $this->connection && $this->selectDB($this->dbname) ){
			return TRUE;
		}

		trigger_error( 'Error connecting to database: '.$this->error ); 
		die();
	}
	
	// perform a select and return single row
	public function row( $sql, $key = null ){
		$r = $this->execute( $sql, $key );
		return isset($r[0]) ? $r[0] : FALSE;
	}
	
	// perform a select and return all the rows
	public function rows( $sql, $key = null ){
		$r = $this->execute( $sql, $key );
		return $r ? $r : FALSE;
	}
	
	// perform single row cached query
	public function cache( $sql, $key = null ){
		if( $result = $this->loadCache($sql) ) return $result;
		return $this->row( $sql, $key );
	}
	
	// perform multiple row cached query
	public function caches( $sql, $key = null ){
		if( $result = $this->loadCache($sql) ) return $result;
		return $this->rows( $sql, $key );
	}
	
	// escape a single string by reference
	public function escape( &$x ){
		$x = addslashes( $x );
	}
	
	// prepare a query for safe execution, using sprintf systax
	public function prepare( $args ){
		// pass in any number of arguments
		$args = func_get_args();
		$sql = array_shift( $args );
		
		array_walk( $args, array($this, 'escape') );
		$sql = @vsprintf( $sql, $args );
		
		return $sql;
	}
	
	// get back some statistics about db load
	public function getStats(){
		return object( array(
			'q' => $this->queryCount,
			'c' => $this->cacheCount
		) );
	}
	
	// loads sql and result from serialized data on filesystem
	protected function loadCache( $sql ){
		$this->cache_filename = md5( $sql ).'.php';
		$this->cache_filepath = ROOT.'/cache/db/'.substr( $this->cache_filename, 0, 2 );
		
		$filepath = $this->cache_filepath.'/'.$this->cache_filename;
		
		if( file_exists($filepath) ){
			include( $filepath );
			
			$res = unserialize($res);
			if( $res ){
				$this->cacheCount ++;
				return $res;
			}
		}
		
		return FALSE;
	}
	
	// stores sql and result as serialized data on filesystem
	protected function writeCache( $res, $sql ){
		$res = serialize( $res );
		
		$file = "<?php\n\n";
		$file .= $this->heredoc( $res, 'res' );
		$file .= $this->heredoc( $sql, 'sql' );
		$file .= $this->heredoc( date("D M jS, Y h:i:s a", $this->now), 'gen' );
		
		$this->cache_filename = md5( $sql ).'.php';
		$this->cache_filepath = ROOT.'/cache/db/'.substr( $this->cache_filename, 0, 2 );
		
		if( !is_dir($this->cache_filepath) ){
			mkdir( $this->cache_filepath );
		}
		
		file_put_contents( $this->cache_filepath.'/'.$this->cache_filename, $file );
	}
	
	// used for building php variables when serializing data
	private function heredoc( $string, $varname = 'h' ){
		$heredoc = 'CHURRO';
		
		// php may try to parse varaibles.  since NOWDOC is 5.3 > ...
		$string = str_replace( '$', '\$', $string );
		
		while( strpos($string, $heredoc) ) $heredoc .= chr( rand(65,90) );
		
		$h = '$'.$varname.' = <<<'.$heredoc."\n".$string."\n".$heredoc.';'."\n\n";
		
		return $h;
	}
}

// end of file
// class_DB.php